#include <Application.h>
#include <Bitmap.h>
#include <View.h>
#include <Window.h>
#include <stdio.h>
#include <string.h>

//#define DUMP_BLENDING_RESULTS
#ifdef DUMP_BLENDING_RESULTS
#include <BitmapStream.h>
#include <File.h>
#include <TranslatorRoster.h>
#include <String.h>
#endif

uint32 kBitmapBits[] = {
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00111111,
	0x00777777, 0x00000000, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00111111,
	0x00777777, 0x00444444, 0x00000000, 0x00000000, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00000000, 0x00000000, 0x00bb0000, 0x00ffffff, 0x00000000,
	0x00444444, 0x00777777, 0x00111111, 0x00000000, 0x00000000, 0x00000000,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00000000, 0x00bb0000, 0x00ee0000, 0x00ee0000,
	0x00ff0000, 0x00ffffff, 0x00ee0000, 0x00111111, 0x00000000, 0x00000000,
	0x00000000, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00bb0000, 0x00ee0000,
	0x00ee0000, 0x00ff0000, 0x00ffffff, 0x00ee0000, 0x00ee0000, 0x00ee0000,
	0x00000000, 0x00000000, 0x00000000, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00bb0000,
	0x00ee0000, 0x00ee0000, 0x00ff0000, 0x00ffffff, 0x00ee0000, 0x00ee0000,
	0x00ee0000, 0x00cc0000, 0x00000000, 0x00000000, 0x00000000, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000,
	0x00bb0000, 0x00ee0000, 0x00ee0000, 0x00ff0000, 0x00ffffff, 0x00ee0000,
	0x00ee0000, 0x00ee0000, 0x00cc0000, 0x00990000, 0x00990000, 0x00000000,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00000000, 0x00ee0000, 0x00ee0000, 0x00ee0000, 0x00ffffff,
	0x00ee0000, 0x00ff0000, 0x00cc0000, 0x00cc0000, 0x00990000, 0x00bb0000,
	0x00880000, 0x00000000, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00000000, 0x00ee0000, 0x00ee0000, 0x00ee0000,
	0x00ffffff, 0x00ee0000, 0x00ff0000, 0x00cc0000, 0x00cc0000, 0x00990000,
	0x00bb0000, 0x00880000, 0x00000000, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00ee0000, 0x00ee0000,
	0x00ee0000, 0x00ffffff, 0x00ee0000, 0x00ff0000, 0x00cc0000, 0x00cc0000,
	0x00990000, 0x00bb0000, 0x00880000, 0x00990000, 0x00000000, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00ee0000,
	0x00ee0000, 0x00ee0000, 0x00ffffff, 0x00ee0000, 0x00ff0000, 0x00cc0000,
	0x00cc0000, 0x00990000, 0x00bb0000, 0x00880000, 0x00990000, 0x00000000,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00000000, 0x00ee0000, 0x00ff0000, 0x00ffffff, 0x00ee0000, 0x00ee0000,
	0x00ee0000, 0x00cc0000, 0x00990000, 0x00bb0000, 0x00880000, 0x00880000,
	0x00000000, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00000000, 0x00ee0000, 0x00ee0000, 0x00ffffff, 0x00ee0000,
	0x00ff0000, 0x00cc0000, 0x00cc0000, 0x00990000, 0x00bb0000, 0x00880000,
	0x00990000, 0x00000000, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00ee0000, 0x00ffffff,
	0x00ee0000, 0x00ff0000, 0x00cc0000, 0x00cc0000, 0x00990000, 0x00bb0000,
	0x00880000, 0x00000000, 0x00000000, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00ff6666,
	0x00ff6666, 0x00ff6666, 0x00ff6666, 0x00880000, 0x00000000, 0x00ee0000,
	0x00ff6666, 0x00000000, 0x00ee0000, 0x00ee0000, 0x00bb0000, 0x00bb0000,
	0x00bb0000, 0x00880000, 0x00000000, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000,
	0x00ee0000, 0x00ff0000, 0x00ee0000, 0x00880000, 0x00990000, 0x00000000,
	0x00ee0000, 0x00ff6666, 0x00880000, 0x00000000, 0x00cc0000, 0x00990000,
	0x00bb0000, 0x00880000, 0x00990000, 0x00000000, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00000000, 0x00ee0000, 0x00ff0000, 0x00ee0000, 0x00880000, 0x00990000,
	0x00000000, 0x00ee0000, 0x00ff6666, 0x00880000, 0x00000000, 0x00990000,
	0x00880000, 0x00880000, 0x00990000, 0x00000000, 0x00000000, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00ff6666, 0x00880000, 0x00000000,
	0x00990000, 0x00880000, 0x00880000, 0x00000000, 0x00000000, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00000000, 0x00444444, 0x00ff6666, 0x00880000,
	0x00000000, 0x00990000, 0x00880000, 0x00880000, 0x00000000, 0x00ee0000,
	0x00000000, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00ff6666,
	0x00880000, 0x00000000, 0x00000000, 0x00000000, 0x00990000, 0x00000000,
	0x00880000, 0x00ee0000, 0x00000000, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00000000,
	0x00ff9900, 0x00000000, 0x00000000, 0x00000000, 0x00444444, 0x00000000,
	0x00000000, 0x00880000, 0x00990000, 0x00ee0000, 0x00000000, 0x00777477,
	0x00777477, 0x00777477, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000,
	0x00ff9900, 0x00ff9900, 0x00ffff00, 0x00ffff00, 0x00ffff00, 0x00000000,
	0x00444444, 0x00000000, 0x00000000, 0x00880000, 0x00ff0000, 0x00ee0000,
	0x00000000, 0x00777477, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477, 0x00777477,
	0x00000000, 0x00ff9900, 0x00ff9900, 0x00ffff00, 0x00ffff00, 0x00ffff00,
	0x00ff9900, 0x00000000, 0x00000000, 0x00777477, 0x00000000, 0x00ee0000,
	0x00ff0000, 0x00880000, 0x00000000, 0x00777477, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00000000, 0x00ff9900, 0x00ff9900, 0x00ffff00,
	0x00ffff00, 0x00ff9900, 0x00000000, 0x00777777, 0x00777777, 0x00777777,
	0x00000000, 0x00ee0000, 0x00990000, 0x00000000, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00ff9900, 0x00ff9900,
	0x00ffff00, 0x00ff9900, 0x00ff9900, 0x00ff9900, 0x00000000, 0x00777777,
	0x00777777, 0x00777777, 0x00000000, 0x00880000, 0x00000000, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000,
	0x00ff9900, 0x00ffff00, 0x00ff9900, 0x00ff9900, 0x00ff9900, 0x00000000,
	0x00777477, 0x00777477, 0x00777477, 0x00777777, 0x00000000, 0x00000000,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00000000, 0x00ff9900, 0x00ffff00, 0x00ff9900, 0x00ff9900, 0x00000000,
	0x00000000, 0x00777477, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00000000, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00000000, 0x00ffff00, 0x00ff9900, 0x00000000,
	0x00000000, 0x00777477, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00000000,
	0x00000000, 0x00777477, 0x00777477, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777477,
	0x00777477, 0x00777477, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777777, 0x00777777, 0x00777777,
	0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777777, 0x00777777,
	0x00777777, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
	0x00777477, 0x00777477, 0x00777477, 0x00777477
};

class DrawingModeView : public BView {
public:
							DrawingModeView(BRect frame);
virtual						~DrawingModeView();

virtual	void				Draw(BRect updateRect);

private:
		BBitmap *			fBitmap;
		BBitmap *			fTriangleLeft;
		BBitmap *			fTriangleRight;
};


class DrawingModeWindow : public BWindow {
public:
							DrawingModeWindow(BRect frame);

private:
		DrawingModeView *	fView;
};


class DrawingModeApp : public BApplication {
public:
							DrawingModeApp();

private:
		DrawingModeWindow *	fWindow;
};


DrawingModeApp::DrawingModeApp()
	:	BApplication("application/x.vnd-Haiku.DrawingModeTest")
{
	fWindow = new DrawingModeWindow(BRect(200, 200, 760, 800));
	fWindow->Show();
}


DrawingModeWindow::DrawingModeWindow(BRect frame)
	:	BWindow(frame, "Drawing Modes Test", B_TITLED_WINDOW,
			B_QUIT_ON_WINDOW_CLOSE)
{
	fView = new DrawingModeView(frame.OffsetToSelf(0, 0));
	AddChild(fView);
	fView->SetViewColor(255, 203, 0);
	fView->SetDrawingMode(B_OP_OVER);
}


DrawingModeView::DrawingModeView(BRect frame)
	:	BView(frame, "DrawingModeView", B_FOLLOW_ALL, B_WILL_DRAW),
		fBitmap(NULL)
{
	fBitmap = new BBitmap(BRect(0, 0, 31, 31), B_RGB32);
	memcpy(fBitmap->Bits(), kBitmapBits, fBitmap->BitsLength());

	uint32 triangleLeftBits[32 * 32] = { 0 };
	uint32 triangleRightBits[32 * 32] = { 0 };
	for(int y = 0; y < 32; ++y) {
		for(int x = 0; x < 32; ++x) {
			if(x < 32 - y) {
				triangleLeftBits[y * 32 + x] = 0xffff0000;
			}
			if(x >= y) {
				triangleRightBits[y * 32 + x] = 0xff0000ff;
			}
		}
	}

	fTriangleLeft = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32);
	memcpy(fTriangleLeft->Bits(), triangleLeftBits,
		fTriangleLeft->BitsLength());
	fTriangleRight = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32);
	memcpy(fTriangleRight->Bits(), triangleRightBits,
		fTriangleRight->BitsLength());
}


DrawingModeView::~DrawingModeView()
{
	delete fBitmap;
	delete fTriangleLeft;
	delete fTriangleRight;
}


void
DrawingModeView::Draw(BRect updateRect)
{
	SetDrawingMode(B_OP_COPY);
	SetLowColor(ViewColor());
	FillRect(Bounds(), B_SOLID_LOW);

	SetLowColor(255, 0, 0);
	SetHighColor(0, 0, 255);

	BRect bitmapBounds = fBitmap->Bounds();
	int32 imageHeight = bitmapBounds.IntegerHeight() + 10;
	int32 imageWidth = bitmapBounds.IntegerWidth() + 10;
	BRect triangleBounds = fTriangleLeft->Bounds();
	int32 triangleHeight = triangleBounds.IntegerHeight() + 10;
	int32 triangleWidth = triangleBounds.IntegerWidth() + 10;

#define MODE(m) { m, #m }

	struct {
		drawing_mode mode;
		const char *name;
	} drawingModes[] = {
		MODE(B_OP_COPY),
		MODE(B_OP_OVER),
		MODE(B_OP_ERASE),
		MODE(B_OP_INVERT),
		MODE(B_OP_SELECT),
		MODE(B_OP_ADD),
		MODE(B_OP_SUBTRACT),
		MODE(B_OP_BLEND),
		MODE(B_OP_MIN),
		MODE(B_OP_MAX)
	};

	struct {
		alpha_function mode;
		const char *name;
	} blendingModes[] = {
		MODE(B_ALPHA_COMPOSITE_SOURCE_OVER),
		MODE(B_ALPHA_COMPOSITE_SOURCE_IN),
		MODE(B_ALPHA_COMPOSITE_SOURCE_OUT),
		MODE(B_ALPHA_COMPOSITE_SOURCE_ATOP),
		MODE(B_ALPHA_COMPOSITE_DESTINATION_OVER),
		MODE(B_ALPHA_COMPOSITE_DESTINATION_IN),
		MODE(B_ALPHA_COMPOSITE_DESTINATION_OUT),
		MODE(B_ALPHA_COMPOSITE_DESTINATION_ATOP),
		MODE(B_ALPHA_COMPOSITE_XOR),
		MODE(B_ALPHA_COMPOSITE_CLEAR),
		MODE(B_ALPHA_COMPOSITE_DIFFERENCE),
		MODE(B_ALPHA_COMPOSITE_LIGHTEN),
		MODE(B_ALPHA_COMPOSITE_DARKEN)
	};

	int32 modeCount = sizeof(drawingModes) / sizeof(drawingModes[0]);
	for (int32 i = 0; i < modeCount; i++) {
		if (drawingModes[i].mode == B_OP_SELECT) {
			// make the background contain the low and high color to see
			// actual effect of B_OP_SELECT
			SetDrawingMode(B_OP_COPY);
			FillRect(BRect(0, imageHeight * i, imageWidth * 2 - 10,
				imageHeight * i + bitmapBounds.Height() / 2), B_SOLID_LOW);
			FillRect(BRect(0, imageHeight * i  + bitmapBounds.Height() / 2,
				imageWidth * 2 - 10, imageHeight * i + bitmapBounds.Height()),
				B_SOLID_HIGH);
		} else if (drawingModes[i].mode == B_OP_MAX
			|| drawingModes[i].mode == B_OP_MIN) {
			// need a darker/lighter color as a background otherwise nothing
			// will be selected from the source
			SetDrawingMode(B_OP_COPY);
			SetHighColor(255, 255, 255);
			FillRect(BRect(0, imageHeight * i, imageWidth * 2 - 10,
				imageHeight * i + bitmapBounds.Height() / 3), B_SOLID_HIGH);
			SetHighColor(128, 128, 128);
			FillRect(BRect(0, imageHeight * i  + bitmapBounds.Height() / 3,
				imageWidth * 2 - 10, imageHeight * i + bitmapBounds.Height()),
				B_SOLID_HIGH);
			SetHighColor(0, 0, 0);
			FillRect(BRect(0, imageHeight * i  + bitmapBounds.Height() / 3 * 2,
				imageWidth * 2 - 10, imageHeight * i + bitmapBounds.Height()),
				B_SOLID_HIGH);
			SetHighColor(0, 0, 255);
		}

		SetDrawingMode(drawingModes[i].mode);
		DrawBitmap(fBitmap, BPoint(0, imageHeight * i));
		FillRect(bitmapBounds.OffsetToCopy(imageWidth,
			imageHeight * i), B_MIXED_COLORS);

		SetDrawingMode(B_OP_OVER);
		DrawString(drawingModes[i].name, BPoint(imageWidth * 2,
			imageHeight * i + 20));
	}

#ifdef DUMP_BLENDING_RESULTS
	BTranslatorRoster* roster = BTranslatorRoster::Default();
	if (roster == NULL)
		abort();

	translator_id* outId;
	int32 outCount;
	translation_format pngFormat;
	roster->GetAllTranslators(&outId, &outCount);
	for(int32 i = 0; i < outCount; ++i) {
		const translation_format* formats;
		int32 formatCount;
		roster->GetOutputFormats(outId[i], &formats, &formatCount);
		for(int32 j = 0; j < formatCount; ++j) {
			if(strcmp(formats[j].MIME, "image/png") == 0) {
				pngFormat = formats[j];
			}
		}
	}

	status_t r = B_OK;
	{
		BFile file("DESTINATION.png",
			B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
		BBitmapStream stream(fTriangleLeft);
		r = roster->Translate(&stream, NULL, NULL, &file, pngFormat.type);
		if(r != B_OK)
			fprintf(stderr, "Failed to save PNG file for destination\n");
		stream.DetachBitmap(&fTriangleLeft);
	}
	{
		BFile file("SOURCE.png", B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
		BBitmapStream stream(fTriangleRight);
		r = roster->Translate(&stream, NULL, NULL, &file, pngFormat.type);
		if(r != B_OK)
			fprintf(stderr, "Failed to save PNG file for source\n");
		stream.DetachBitmap(&fTriangleRight);
	}
#endif

	modeCount = sizeof(blendingModes) / sizeof(blendingModes[0]);
	const int columnOffset = 180;
	BView *blitter = new BView(BRect(0, 0, 31, 31),
		"blitter", B_FOLLOW_ALL, B_WILL_DRAW);
	BBitmap *resultBitmap = new BBitmap(BRect(0, 0, 31, 31),
		B_RGBA32, true, false);
	resultBitmap->AddChild(blitter);
	for (int32 i = 0; i < modeCount; i++) {
		resultBitmap->Lock();
		blitter->SetDrawingMode(B_OP_COPY);
		blitter->SetHighColor(0, 0, 0, 0);
		blitter->FillRect(resultBitmap->Bounds());
		blitter->DrawBitmap(fTriangleLeft, B_ORIGIN);
		blitter->SetDrawingMode(B_OP_ALPHA);
		blitter->SetBlendingMode(B_PIXEL_ALPHA, blendingModes[i].mode);
		blitter->DrawBitmap(fTriangleRight, B_ORIGIN);
		resultBitmap->Unlock();

#ifdef DUMP_BLENDING_RESULTS
		BBitmapStream stream(resultBitmap);
		BString fileName(blendingModes[i].name);
		BFile file(fileName.Append(".png"),
			B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);

		r = roster->Translate(&stream, NULL, NULL, &file, pngFormat.type);
		if(r != B_OK) {
			fprintf(stderr, "Failed to save PNG file for %s\n",
				blendingModes[i].name);
		}

		stream.DetachBitmap(&resultBitmap);
#endif

		SetDrawingMode(B_OP_ALPHA);
		SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
		DrawBitmap(resultBitmap, BPoint(columnOffset, triangleHeight * i));

		SetDrawingMode(B_OP_OVER);
		DrawString(blendingModes[i].name, BPoint(columnOffset + triangleWidth,
			triangleHeight * i + 20));
	}
	resultBitmap->Lock();
	resultBitmap->RemoveChild(blitter);
	delete resultBitmap;
	delete blitter;
}


int
main(int argc, const char *argv[])
{
	DrawingModeApp *app = new DrawingModeApp();
	app->Run();
	delete app;
	return 0;
}
